#ifndef __RING_QUEUE_HPP__
#define __RING_QUEUE_HPP__


#include <iostream>
#include <string>
#include <vector>
#include <pthread.h>
#include <semaphore.h>

template<typename T>
class RingQueue
{
    private:
    void P(sem_t& sg)
    {
        sem_wait(&sg);//p操作对应的函数，执行该函数，信号量资源如果大于0，则减减
    }
    void V(sem_t& sg)
    {
        sem_post(&sg);
    }
    void Lock(pthread_mutex_t& mutex)
    {
        pthread_mutex_lock(&mutex);
    }
    void Unlock(pthread_mutex_t& mutex)
    {
        pthread_mutex_unlock(&mutex);
    }
    public:
    RingQueue(int cap)
    :_cap(cap),_ring_queue(cap)
    {
        _productor_step = 0;
        _consumer_step = 0;

        pthread_mutex_init(&_productor_mutex,nullptr);
        pthread_mutex_init(&_consumer_mutex,nullptr);

        sem_init(&_room_sem,0,_cap);
        sem_init(&_data_sem,0,0);
    }
    ~RingQueue()
    {
        sem_destroy(&_room_sem);
        sem_destroy(&_data_sem);

        pthread_mutex_destroy(&_productor_mutex);
        pthread_mutex_destroy(&_consumer_mutex);
    }
    void Enqueue(const T& in)
    {
        
        //生产任务
        //P操作申请一个空间
        P(_room_sem);
        //多个生产者进程之间要互斥
        Lock(_productor_mutex);
        _ring_queue[_productor_step++] = in;//生产者按照顺序生产
        _productor_step %= _cap;

        Unlock(_productor_mutex);
        V(_data_sem);
        

    }
    void Pop(T* out)
    {
        P(_data_sem);
        Lock(_consumer_mutex);

        *out = _ring_queue[_consumer_step++];
        _consumer_step %= _cap;

        Unlock(_consumer_mutex);
        V(_room_sem);
    }
    private:
    //1.定义一个环形队列
    std::vector<T> _ring_queue;
    int _cap;//环形队列的容量上限

    //2.生产者和消费者的下标
    int _productor_step;
    int _consumer_step;

    //3.定义信号量
    sem_t _room_sem;//生产者关心有几个空间
    sem_t _data_sem;//消费者关心有几个数据

    //4.定义锁，维护多生产多消费之间的互斥的关系，
    //注意生产者和消费者之间不需要互斥，因此需要两把锁
    pthread_mutex_t _productor_mutex;
    pthread_mutex_t _consumer_mutex;
    
};


#endif